home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / DCLAP 6d / dclap6d / vibrant / mapping.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-05  |  13.7 KB  |  410 lines  |  [TEXT/R*ch]

  1. /*   mapping.c
  2. * ===========================================================================
  3. *
  4. *                            PUBLIC DOMAIN NOTICE
  5. *            National Center for Biotechnology Information (NCBI)
  6. *
  7. *  This software/database is a "United States Government Work" under the
  8. *  terms of the United States Copyright Act.  It was written as part of
  9. *  the author's official duties as a United States Government employee and
  10. *  thus cannot be copyrighted.  This software/database is freely available
  11. *  to the public for use. The National Library of Medicine and the U.S.
  12. *  Government do not place any restriction on its use or reproduction.
  13. *  We would, however, appreciate having the NCBI and the author cited in
  14. *  any work or product based on this material
  15. *
  16. *  Although all reasonable efforts have been taken to ensure the accuracy
  17. *  and reliability of the software and data, the NLM and the U.S.
  18. *  Government do not and cannot warrant the performance or results that
  19. *  may be obtained by using this software or data. The NLM and the U.S.
  20. *  Government disclaim all warranties, express or implied, including
  21. *  warranties of performance, merchantability or fitness for any particular
  22. *  purpose.
  23. *
  24. * ===========================================================================
  25. *
  26. * File Name:  mapping.c
  27. *
  28. * Author:  Jonathan Kans, Jill Shermer
  29. *
  30. * Version Creation Date:   1/19/93
  31. *
  32. * $Revision: 1.12 $
  33. *
  34. * File Description: 
  35. *
  36. * Modifications:  
  37. * --------------------------------------------------------------------------
  38. * Date     Name        Description of modification
  39. * -------  ----------  -----------------------------------------------------
  40. *
  41. *
  42. * ==========================================================================
  43. */
  44.  
  45. #ifndef _VIBRANT_
  46. #include <vibrant.h>
  47. #endif
  48.  
  49. #ifndef _PICTURE_
  50. #include <picture.h>
  51. #endif
  52.  
  53. #ifndef _PICTUREP_
  54. #include <pictureP.h>
  55. #endif
  56.  
  57. #ifndef _MAPPINGP_
  58. #include <mappingP.h>
  59. #endif
  60.  
  61. /*****************************************************************************
  62. *
  63. *   STATIC VARIABLES
  64. *
  65. *****************************************************************************/
  66.  
  67. static RecT  emptyRect = {0, 0, 0, 0};
  68.  
  69. /*****************************************************************************
  70. *
  71. *   LoadBox (box, left, top, right, bottom)
  72. *       Initializes a box structure with the specified parameters
  73. *
  74. *****************************************************************************/
  75.  
  76. static void LoadBox (BoxPtr box, Int4 left, Int4 top, Int4 right, Int4 bottom)
  77.  
  78. {
  79.   if (box != NULL) {
  80.     box->left = left;
  81.     box->top = top;
  82.     box->right = right;
  83.     box->bottom = bottom;
  84.   }
  85. }
  86.  
  87. /*****************************************************************************
  88. *
  89. *   MapX (pntX, scale)
  90. *       Maps a horizontal world coordinate to an Int4 in viewer coordinates
  91. *
  92. *****************************************************************************/
  93.  
  94. static Int4 MapX (Int4 pntX, ScaleInfo *scale)
  95.  
  96. {
  97.   return (Int4) scale->view.left + (pntX - scale->port.left) / scale->scaleX;
  98. }
  99.  
  100. /*****************************************************************************
  101. *
  102. *   MapY (pntY, scale)
  103. *       Maps a vertical world coordinate to an Int4 in viewer coordinates
  104. *
  105. *****************************************************************************/
  106.  
  107. static Int4 MapY (Int4 pntY, ScaleInfo *scale)
  108.  
  109. {
  110.   return (Int4) scale->view.bottom - (pntY - scale->port.bottom) / scale->scaleY;
  111. }
  112.  
  113. /*****************************************************************************
  114. *
  115. *   BoxInViewport (rct, box, mrg, scale)
  116. *       Determines whether a box is visible in the viewport
  117. *
  118. *****************************************************************************/
  119.  
  120. Boolean BoxInViewport (RectPtr rct, BoxPtr box, RectPtr mrg, ScaleInfo *scale)
  121.  
  122. {
  123.   if (box != NULL && mrg != NULL && scale != NULL &&
  124.     MAX (box->left + (Int4) mrg->left * scale->scaleX, scale->port.left) <=
  125.     MIN (box->right + (Int4) mrg->right * scale->scaleX, scale->port.right) &&
  126.     MAX (box->bottom - (Int4) mrg->bottom * scale->scaleY, scale->port.bottom) <=
  127.     MIN (box->top - (Int4) mrg->top * scale->scaleY, scale->port.top)) {
  128.     if (rct != NULL) {
  129.       rct->left = (Int2) MAX (MapX (box->left, scale), (Int4) (scale->view.left - 20));
  130.       rct->top = (Int2) MAX (MapY (box->top, scale), (Int4) (scale->view.top - 20));
  131.       rct->right = (Int2) MIN (MapX (box->right, scale), (Int4) (scale->view.right + 20));
  132.       rct->bottom = (Int2) MIN (MapY (box->bottom, scale), (Int4) (scale->view.bottom + 20));
  133.     }
  134.     return TRUE;
  135.   } else {
  136.     return FALSE;
  137.   }
  138. }
  139.  
  140. /*****************************************************************************
  141. *
  142. *   ClipPoint (clp1, clp2, mrg, scale)
  143. *       Clips the first pnt of a line in world coordinates to the port
  144. *
  145. *****************************************************************************/
  146.  
  147. static Boolean ClipPoint (PntPtr clp1, PntPtr clp2, RectPtr mrg, ScaleInfo *scale)
  148.  
  149. {
  150.   BoxInfo  bounds;
  151.   BoxInfo  box;
  152.   Int4     deltaX;
  153.   Int4     deltaY;
  154.   Int2     maxClip;
  155.  
  156.   if (clp1 != NULL && clp2 != NULL && scale != NULL) {
  157.     LoadBox (&bounds,
  158.              scale->port.left - 20 * scale->scaleX, scale->port.top + 20 * scale->scaleY,
  159.              scale->port.right + 20 * scale->scaleX, scale->port.bottom - 20 * scale->scaleY);
  160.     maxClip = 2;
  161.     do {
  162.       LoadBox (&box, MIN (clp1->x, clp2->x), MAX (clp1->y, clp2->y),
  163.                MAX (clp1->x, clp2->x), MIN (clp1->y, clp2->y));
  164.       if (BoxInViewport (NULL, &box, mrg, scale)) {
  165.         if (PntInBox (&bounds, clp1, mrg, scale)) {
  166.           return TRUE;
  167.         } else {
  168.           deltaX = (clp2->x - clp1->x);
  169.           deltaY = (clp2->y - clp1->y);
  170.           if (clp1->y > bounds.top) {
  171.             clp1->x += deltaX * (bounds.top - clp1->y) / deltaY;
  172.             clp1->y = bounds.top;
  173.           } else if (clp1->y < bounds.bottom) {
  174.             clp1->x += deltaX * (bounds.bottom - clp1->y) / deltaY;
  175.             clp1->y = bounds.bottom;
  176.           } else if (clp1->x > bounds.right) {
  177.             clp1->y += deltaY * (bounds.right - clp1->x) / deltaX;
  178.             clp1->x = bounds.right;
  179.           } else if (clp1->x < bounds.left) {
  180.             clp1->y += deltaY * (bounds.bottom - clp1->x) / deltaX;
  181.             clp1->x = bounds.bottom;
  182.           }
  183.         }
  184.       } else {
  185.         return FALSE;
  186.       }
  187.       maxClip--;
  188.     } while (maxClip > 0);
  189.   }
  190.   if (PntInBox (&bounds, clp1, mrg, scale)) {
  191.     return TRUE;
  192.   } else {
  193.     return FALSE;
  194.   }
  195. }
  196.  
  197. /*****************************************************************************
  198. *
  199. *   LineInViewport (pt1, pt2, pnt1, pnt2, mrg, scale)
  200. *       Determines whether a line is visible in the viewport
  201. *
  202. *****************************************************************************/
  203.  
  204. Boolean LineInViewport (PointPtr pt1, PointPtr pt2, PntPtr pnt1,
  205.                         PntPtr pnt2, RectPtr mrg, ScaleInfo *scale)
  206.  
  207. {
  208.   BoxInfo  box;
  209.   PntInfo  clp1;
  210.   PntInfo  clp2;
  211.  
  212.   if (pnt1 != NULL && pnt2 != NULL && mrg != NULL && scale != NULL) {
  213.     clp1 = *(pnt1);
  214.     clp2 = *(pnt2);
  215.     LoadBox (&box, MIN (clp1.x, clp2.x), MAX (clp1.y, clp2.y),
  216.              MAX (clp1.x, clp2.x), MIN (clp1.y, clp2.y));
  217.     if (BoxInViewport (NULL, &box, mrg, scale)) {
  218.       if (clp1.x == clp2.x) {
  219.         if (pt1 != NULL && pt2 != NULL) {
  220.           pt1->x = pt2->x = (Int2) MapX (clp1.x, scale);
  221.           if (clp1.y > clp2.y) {
  222.             pt1->y = (Int2) MAX (MapY (clp1.y, scale), (Int4) scale->view.top - 20);
  223.             pt2->y = (Int2) MIN (MapY (clp2.y, scale), (Int4) scale->view.bottom + 20);
  224.           } else if (clp1.y < clp2.y) {
  225.             pt2->y = (Int2) MAX (MapY (clp2.y, scale), (Int4) scale->view.top - 20);
  226.             pt1->y = (Int2) MIN (MapY (clp1.y, scale), (Int4) scale->view.bottom + 20);
  227.           } else {
  228.             pt1->y = pt2->y = (Int2) MapY (clp1.y, scale);
  229.           }
  230.         }
  231.         return TRUE;
  232.       } else if (clp1.y == clp2.y) {
  233.         if (pt1 != NULL && pt2 != NULL) {
  234.           pt1->y = pt2->y = (Int2) MapY (clp1.y, scale);
  235.           if (clp1.x > clp2.x) {
  236.             pt1->x = (Int2) MIN (MapX (clp1.x, scale), (Int4) scale->view.right + 20);
  237.             pt2->x = (Int2) MAX (MapX (clp2.x, scale), (Int4) scale->view.left - 20);
  238.           } else if (clp1.x < clp2.x) {
  239.             pt2->x = (Int2) MIN (MapX (clp2.x, scale), (Int4) scale->view.right + 20);
  240.             pt1->x = (Int2) MAX (MapX (clp1.x, scale), (Int4) scale->view.left - 20);
  241.           } else {
  242.             pt1->x = pt2->x = (Int2) MapX (clp1.x, scale);
  243.           }
  244.         }
  245.         return TRUE;
  246.       } else if (ClipPoint (&clp1, &clp2, mrg, scale) && ClipPoint (&clp2, &clp1, mrg, scale)) {
  247.         if (pt1 != NULL && pt2 != NULL) {
  248.           pt1->x = (Int2) MapX (clp1.x, scale);
  249.           pt1->y = (Int2) MapY (clp1.y, scale);
  250.           pt2->x = (Int2) MapX (clp2.x, scale);
  251.           pt2->y = (Int2) MapY (clp2.y, scale);
  252.         }
  253.         return TRUE;
  254.       } else {
  255.         return FALSE;
  256.       }
  257.     } else {
  258.       return FALSE;
  259.     }
  260.   } else {
  261.     return FALSE;
  262.   }
  263. }
  264.  
  265. /*****************************************************************************
  266. *
  267. *   PntInViewport (pt, pnt, mrg, scale)
  268. *       Determines whether a pnt is visible in the viewport
  269. *
  270. *****************************************************************************/
  271.  
  272. Boolean PntInViewport (PointPtr pt, PntPtr pnt, RectPtr mrg, ScaleInfo *scale)
  273.  
  274. {
  275.   if (pnt != NULL && mrg != NULL && scale != NULL &&
  276.     MAX (pnt->x + (Int4) mrg->left * scale->scaleX, scale->port.left) <=
  277.     MIN (pnt->x + (Int4) mrg->right * scale->scaleX, scale->port.right) &&
  278.     MAX (pnt->y - (Int4) mrg->bottom * scale->scaleY, scale->port.bottom) <=
  279.     MIN (pnt->y - (Int4) mrg->top * scale->scaleY, scale->port.top)) {
  280.     if (pt != NULL) {
  281.       pt->x = (Int2) MapX (pnt->x, scale);
  282.       pt->y = (Int2) MapY (pnt->y, scale);
  283.     }
  284.     return TRUE;
  285.   } else {
  286.     return FALSE;
  287.   }
  288. }
  289.  
  290. /*****************************************************************************
  291. *
  292. *   MapWorldPointToPixel (pt, pnt, scale)
  293. *       Maps a pnt in world coordinates to a point in viewer coordinates
  294. *
  295. *****************************************************************************/
  296.  
  297. void MapWorldPointToPixel (PointPtr pt, PntPtr pnt, ScaleInfo *scale)
  298.  
  299. {
  300.   if (pt != NULL && pnt != NULL && scale != NULL) {
  301.     pt->x = (Int2) MapX (pnt->x, scale);
  302.     pt->y = (Int2) MapY (pnt->y, scale);
  303.   }
  304. }
  305.  
  306. /*****************************************************************************
  307. *
  308. *   MapPixelPointToWorld (pnt, pt, scale)
  309. *       Maps a point in viewer coordinates to a pnt in world coordinates
  310. *
  311. *****************************************************************************/
  312.  
  313. void MapPixelPointToWorld (PntPtr pnt, PointPtr pt, ScaleInfo *scale)
  314.  
  315. {
  316.   if (pnt != NULL && pt != NULL && scale != NULL) {
  317.     pnt->x = (Int4) (pt->x - scale->view.left) * scale->scaleX + scale->port.left;
  318.     pnt->y = (Int4) (scale->view.bottom - pt->y) * scale->scaleY + scale->port.bottom;
  319.   }
  320. }
  321.  
  322. /*****************************************************************************
  323. *
  324. *   PntInBox (box, pnt, mrg, scale)
  325. *       Determines whether a box contains a pnt in world coordinates
  326. *
  327. *****************************************************************************/
  328.  
  329. Boolean PntInBox (BoxPtr box, PntPtr pnt, RectPtr mrg, ScaleInfo *scale)
  330.  
  331. {
  332.   if (box != NULL && pnt != NULL && mrg != NULL && scale != NULL) {
  333.     return (Boolean) (pnt->x >= box->left + (Int4) mrg->left * scale->scaleX &&
  334.                       pnt->x <= box->right + (Int4) mrg->right * scale->scaleX &&
  335.                       pnt->y <= box->top - (Int4) mrg->top * scale->scaleY &&
  336.                       pnt->y >= box->bottom - (Int4) mrg->bottom * scale->scaleY);
  337.   } else {
  338.     return FALSE;
  339.   }
  340. }
  341.  
  342. /*****************************************************************************
  343. *
  344. *   MapToRect (r, pt, width, height, offset, align)
  345. *       Creates a rectangle from point, width, height, offset, and align parameters
  346. *
  347. *****************************************************************************/
  348.  
  349. void MapToRect (RectPtr r, PoinT pt, Int2 width,
  350.                 Int2 height, Int2 offset, Uint2 align)
  351.  
  352. {
  353.   Int2  left;
  354.   Int2  top;
  355.  
  356.   if (r != NULL) {
  357.     if (align >= MIDDLE_CENTER && align <= MIDDLE_RIGHT) {
  358.       switch (align) {
  359.         case MIDDLE_CENTER :
  360.           left = pt.x - width / 2;
  361.           top = pt.y - height / 2;
  362.           LoadRect (r, left, top, left + width, top + height);
  363.           OffsetRect (r, 0, 0);
  364.           break;
  365.         case UPPER_LEFT :
  366.           LoadRect (r, pt.x - width, pt.y - height, pt.x, pt.y);
  367.           OffsetRect (r, -offset, -offset);
  368.           break;
  369.         case LOWER_LEFT :
  370.           LoadRect (r, pt.x - width, pt.y, pt.x, pt.y + height);
  371.           OffsetRect (r, -offset, offset);
  372.           break;
  373.         case UPPER_RIGHT :
  374.           LoadRect (r, pt.x, pt.y - height, pt.x + width, pt.y);
  375.           OffsetRect (r, offset, -offset);
  376.           break;
  377.         case LOWER_RIGHT :
  378.           LoadRect (r, pt.x, pt.y, pt.x + width, pt.y + height);
  379.           OffsetRect (r, offset, offset);
  380.           break;
  381.         case UPPER_CENTER :
  382.           left = pt.x - width / 2;
  383.           LoadRect (r, left, pt.y - height, left + width, pt.y);
  384.           OffsetRect (r, 0, -offset);
  385.           break;
  386.         case LOWER_CENTER :
  387.           left = pt.x - width / 2;
  388.           LoadRect (r, left, pt.y, left + width, pt.y + height);
  389.           OffsetRect (r, 0, offset);
  390.           break;
  391.         case MIDDLE_LEFT :
  392.           top = pt.y - height / 2;
  393.           LoadRect (r, pt.x - width, top, pt.x, top + height);
  394.           OffsetRect (r, -offset, 0);
  395.           break;
  396.         case MIDDLE_RIGHT :
  397.           top = pt.y - height / 2;
  398.           LoadRect (r, pt.x, top, pt.x + width, top + height);
  399.           OffsetRect (r, offset, 0);
  400.           break;
  401.         default :
  402.           break;
  403.       }
  404.     } else {
  405.       LoadRect (r, 0, 0, 0, 0);
  406.       Message (MSG_ERROR, "Undefined align value");
  407.     }
  408.   }
  409. }
  410.